#include "DoorModel.h"
#include "Common/DataStructureMacro.h"
#include "Common/Information.h"
#include "ssas_api.h"
#include "audio_service_api.h"
#define LOG_TAG "HMI"
#include "log_api.h"

#define DOOR_AUDIO_ID AUDIO_4

typedef enum 
{
    ALWAYS_OFF,
    ALWAYS_ON,
} MachineState;

typedef enum 
{
    IDLE,
    LIGHT_ALARM,
    DOOR_ALARM,
} OnChildMachineState;

static MachineState currentStatus;
static OnChildMachineState childCurrentStatus;
static uint16_t rawPDAjrSwAtv;
static uint16_t rawDDAjrSwAtv;
static Option_U8 showFlag;
static uint8_t      widget_visible_mask = 0;

uint16_t isDriverDoorOpen()
{
    return rawPDAjrSwAtv;
}

static void init()
{
    currentStatus = ALWAYS_OFF;
    childCurrentStatus = ALWAYS_ON;
    rawPDAjrSwAtv = 0;
    rawDDAjrSwAtv = 0;
    showFlag.value_ = 0;
    showFlag.update_ = false;
}

static MachineState getNewState()
{
    MachineState newState = ALWAYS_OFF;
    int msgState = COM_MSG_INIT;
    Std_ReturnType comRet = E_NOT_OK;
    do
    {
        msgState = get_message_state(COM_IC_LS_DEVICE_INFORMATION);
        if(COM_MSG_TIMEOUT == msgState || COM_MSG_INIT == msgState/*todo maybe remove*/)
        {
            newState = ALWAYS_OFF;
            break;
        }

        comRet = Com_ReceiveSignal(COM_SID_DDAjrSwAtv, &rawPDAjrSwAtv);
        if(E_NOT_OK == comRet)
        {
            newState = ALWAYS_OFF;
            break;
        }

        comRet = Com_ReceiveSignal(COM_SID_PDAjrSwAtv, &rawDDAjrSwAtv);
        if(E_NOT_OK == comRet)
        {
            newState = ALWAYS_OFF;
            break;
        }

        if(DOOR_CLOSE == rawPDAjrSwAtv && DOOR_CLOSE == rawDDAjrSwAtv)
        {
            newState = ALWAYS_OFF;
        }
        else
        {
            newState = ALWAYS_ON;
        }

    } while (false);
    
    return newState;
}

static void leaveOn()
{
    if(childCurrentStatus == DOOR_ALARM)
    {
        stop_sound_request(DOOR_AUDIO_ID);
    }
    else
    {
        //ignore
    }
    childCurrentStatus = IDLE;
}

static void entryOn()
{
    OnChildMachineState newState = IDLE;
    float speed = 0.0f;
    getShowSpeed(&speed);
    if((int)speed >= 10)
    {
        newState = DOOR_ALARM;
    }
    else
    {
        newState = IDLE;
    }

    if(newState == DOOR_ALARM)
    {
        play_sound_request(DOOR_AUDIO_ID, 500, 500, 60000);
    }
    else
    {
        //maybe stop todo
    }
}

static void handleExecuteOn()
{
    float speed = 0.0f;
    getShowSpeed(&speed);
    if(DOOR_ALARM == childCurrentStatus)
    {
        if(speed < 5.0f)
        {
            childCurrentStatus = IDLE;
            stop_sound_request(DOOR_AUDIO_ID);
        }
    }
    else
    {
        if((int)speed >= 10)
        {
            childCurrentStatus = DOOR_ALARM;
            play_sound_request(DOOR_AUDIO_ID, 500, 500, 60000);
        }
    }
}

static void handlStateTransition(MachineState newStatus)
{
    if(newStatus != currentStatus)
    {
        switch (newStatus)
        {
            case ALWAYS_OFF:
            {
                leaveOn();
                break;
            }

            case ALWAYS_ON:
            {
                break;
            }
            
            default:
            {
                LOG_E("unknow status : %d\n", newStatus);
                break;
            }
        }

        currentStatus = newStatus;

        switch (currentStatus)
        {
            case ALWAYS_OFF:
            {
                break;
            }

            case ALWAYS_ON:
            {
                entryOn();
                break;
            }
            
            default:
            {
                LOG_E("unknow status : %d\n", currentStatus);
                break;
            }
        }
    }
    
}

static void postprocess()
{
    switch (currentStatus)
    {
        case ALWAYS_OFF:
        {
            setOptionValue_U8(&showFlag, false);
            break;
        }

        case ALWAYS_ON:
        {
            handleExecuteOn();
            setOptionValue_U8(&showFlag, true);
            break;
        }
        
        default:
        {
            LOG_E("unknow status : %d\n", currentStatus);
            break;
        }
    }
}

static void run()
{
    MachineState newStatus = getNewState();
    handlStateTransition(newStatus);
    postprocess(); 
}

static void release()
{

}

DoorModel g_DoorModelInstance = {
    {
        init,
        run,
        release,
        MIN_PERIOD,
    },
};

// ----------------------------------View------------------------------
void refresh_tt4View(ItuElement* elememt, bool isUnconditional)
{
    if(showFlag.update_)
    {
        ituCheckBoxSetChecked((ITUCheckBox*)elememt->widget_, showFlag.value_);
        showFlag.update_ = false;
    }
}

void reporting_self_validity_tt4View(ItuElement* elememt)
{
    uint8_t is_visible = (elememt && elememt->isVaild_) ? 0x01 : 0x00;
    widget_visible_mask <<= 1;
    widget_visible_mask |= is_visible;
}